home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / DEMOS / BLUEPONY / READTEX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  6.9 KB  |  308 lines

  1. /* readtex.c */
  2.  
  3. /* 
  4.  * Read an SGI .rgb image file and generate a mipmap texture set.
  5.  * Much of this code was borrowed from SGI's tk OpenGL toolkit.
  6.  */
  7.  
  8. #include <GL/glut.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12.  
  13. #include "readtex.h"
  14.  
  15. #ifndef SEEK_SET
  16. #define SEEK_SET 0
  17. #endif
  18.  
  19. /* RGB Image Structure */
  20.  
  21. typedef struct _TK_RGBImageRec {
  22.   GLint sizeX, sizeY;
  23.   GLint components;
  24.   unsigned char *data;
  25. } TK_RGBImageRec;
  26.  
  27. /******************************************************************************/
  28.  
  29. typedef struct _rawImageRec {
  30.   unsigned short imagic;
  31.   unsigned short type;
  32.   unsigned short dim;
  33.   unsigned short sizeX, sizeY, sizeZ;
  34.   unsigned long min, max;
  35.   unsigned long wasteBytes;
  36.   char name[80];
  37.   unsigned long colorMap;
  38.   FILE *file;
  39.   unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
  40.   unsigned long rleEnd;
  41.   GLuint *rowStart;
  42.   GLint *rowSize;
  43. } rawImageRec;
  44.  
  45. /******************************************************************************/
  46.  
  47. static void 
  48. ConvertShort(unsigned short *array, size_t length)
  49. {
  50.   unsigned short b1, b2;
  51.   unsigned char *ptr;
  52.  
  53.   ptr = (unsigned char *) array;
  54.   while (length--) {
  55.     b1 = *ptr++;
  56.     b2 = *ptr++;
  57.     *array++ = (b1 << 8) | (b2);
  58.   }
  59. }
  60.  
  61. static void 
  62. ConvertLong(GLuint * array, size_t length)
  63. {
  64.   unsigned long b1, b2, b3, b4;
  65.   unsigned char *ptr;
  66.  
  67.   ptr = (unsigned char *) array;
  68.   while (length--) {
  69.     b1 = *ptr++;
  70.     b2 = *ptr++;
  71.     b3 = *ptr++;
  72.     b4 = *ptr++;
  73.     *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
  74.   }
  75. }
  76.  
  77. static rawImageRec *
  78. RawImageOpen(const char *fileName)
  79. {
  80.   union {
  81.     int testWord;
  82.     char testByte[4];
  83.   } endianTest;
  84.   rawImageRec *raw;
  85.   GLenum swapFlag;
  86.   int x;
  87.  
  88.   endianTest.testWord = 1;
  89.   if (endianTest.testByte[0] == 1) {
  90.     swapFlag = GL_TRUE;
  91.   } else {
  92.     swapFlag = GL_FALSE;
  93.   }
  94.  
  95.   raw = (rawImageRec *) malloc(sizeof(rawImageRec));
  96.   if (raw == NULL) {
  97.     fprintf(stderr, "Out of memory!\n");
  98.     return NULL;
  99.   }
  100.   if ((raw->file = fopen(fileName, "rb")) == NULL) {
  101.     perror(fileName);
  102.     return NULL;
  103.   }
  104.   fread(raw, 1, 12, raw->file);
  105.  
  106.   if (swapFlag) {
  107.     ConvertShort(&raw->imagic, 6);
  108.   }
  109.   raw->tmp = (unsigned char *) malloc(raw->sizeX * 256);
  110.   if (raw->tmp == NULL) {
  111.     fprintf(stderr, "Out of memory!\n");
  112.     return NULL;
  113.   }
  114.   raw->tmpR = (unsigned char *) malloc(raw->sizeX * 256);
  115.   if (raw->tmpR == NULL) {
  116.     fprintf(stderr, "Out of memory!\n");
  117.     return NULL;
  118.   }
  119.   if (raw->sizeZ > 1) {
  120.     raw->tmpG = (unsigned char *) malloc(raw->sizeX * 256);
  121.     raw->tmpB = (unsigned char *) malloc(raw->sizeX * 256);
  122.     if (raw->tmpG == NULL || raw->tmpB == NULL) {
  123.       fprintf(stderr, "Out of memory!\n");
  124.       return NULL;
  125.     }
  126.     if (raw->sizeZ == 4) {
  127.       raw->tmpA = (unsigned char *) malloc(raw->sizeX * 256);
  128.       if (raw->tmpA == NULL) {
  129.         fprintf(stderr, "Out of memory!\n");
  130.         return NULL;
  131.       }
  132.     }
  133.   }
  134.   if ((raw->type & 0xFF00) == 0x0100) {
  135.     x = raw->sizeY * raw->sizeZ * sizeof(GLuint);
  136.     raw->rowStart = (GLuint *) malloc(x);
  137.     raw->rowSize = (GLint *) malloc(x);
  138.     if (raw->rowStart == NULL || raw->rowSize == NULL) {
  139.       fprintf(stderr, "Out of memory!\n");
  140.       return NULL;
  141.     }
  142.     raw->rleEnd = 512 + (2 * x);
  143.     fseek(raw->file, 512, SEEK_SET);
  144.     fread(raw->rowStart, 1, x, raw->file);
  145.     fread(raw->rowSize, 1, x, raw->file);
  146.     if (swapFlag) {
  147.       ConvertLong(raw->rowStart, x / sizeof(GLuint));
  148.       ConvertLong((GLuint *) raw->rowSize, x / sizeof(GLint));
  149.     }
  150.   }
  151.   return raw;
  152. }
  153.  
  154. static void 
  155. RawImageClose(rawImageRec * raw)
  156. {
  157.  
  158.   fclose(raw->file);
  159.   free(raw->tmp);
  160.   free(raw->tmpR);
  161.   free(raw->tmpG);
  162.   free(raw->tmpB);
  163.   if (raw->sizeZ > 3) {
  164.     free(raw->tmpA);
  165.   }
  166.   free(raw);
  167. }
  168.  
  169. static void 
  170. RawImageGetRow(rawImageRec * raw, unsigned char *buf, int y, int z)
  171. {
  172.   unsigned char *iPtr, *oPtr, pixel;
  173.   int count;
  174.  
  175.   if ((raw->type & 0xFF00) == 0x0100) {
  176.     fseek(raw->file, (long) raw->rowStart[y + z * raw->sizeY], SEEK_SET);
  177.     fread(raw->tmp, 1, (size_t) raw->rowSize[y + z * raw->sizeY],
  178.       raw->file);
  179.  
  180.     iPtr = raw->tmp;
  181.     oPtr = buf;
  182.     for (;;) {
  183.       pixel = *iPtr++;
  184.       count = (int) (pixel & 0x7F);
  185.       if (!count) {
  186.         return;
  187.       }
  188.       if (pixel & 0x80) {
  189.         while (count--) {
  190.           *oPtr++ = *iPtr++;
  191.         }
  192.       } else {
  193.         pixel = *iPtr++;
  194.         while (count--) {
  195.           *oPtr++ = pixel;
  196.         }
  197.       }
  198.     }
  199.   } else {
  200.     fseek(raw->file, 512 + (y * raw->sizeX) + (z * raw->sizeX * raw->sizeY),
  201.       SEEK_SET);
  202.     fread(buf, 1, raw->sizeX, raw->file);
  203.   }
  204. }
  205.  
  206. static void 
  207. RawImageGetData(rawImageRec * raw, TK_RGBImageRec * final)
  208. {
  209.   unsigned char *ptr;
  210.   int i, j;
  211.  
  212.   final->data = (unsigned char *) malloc((raw->sizeX + 1) * (raw->sizeY + 1) * 4);
  213.   if (final->data == NULL) {
  214.     fprintf(stderr, "Out of memory!\n");
  215.   }
  216.   ptr = final->data;
  217.   for (i = 0; i < (int) (raw->sizeY); i++) {
  218.     RawImageGetRow(raw, raw->tmpR, i, 0);
  219.     if (raw->sizeZ > 1) {
  220.       RawImageGetRow(raw, raw->tmpG, i, 1);
  221.       RawImageGetRow(raw, raw->tmpB, i, 2);
  222.       if (raw->sizeZ > 3) {
  223.         RawImageGetRow(raw, raw->tmpA, i, 3);
  224.       }
  225.     }
  226.     for (j = 0; j < (int) (raw->sizeX); j++) {
  227.       *ptr++ = *(raw->tmpR + j);
  228.       if (raw->sizeZ > 1) {
  229.         *ptr++ = *(raw->tmpG + j);
  230.         *ptr++ = *(raw->tmpB + j);
  231.         if (raw->sizeZ > 3) {
  232.           *ptr++ = *(raw->tmpA + j);
  233.         }
  234.       }
  235.     }
  236.   }
  237. }
  238.  
  239. static TK_RGBImageRec *
  240. tkRGBImageLoad(const char *fileName)
  241. {
  242.   rawImageRec *raw;
  243.   TK_RGBImageRec *final;
  244.  
  245.   raw = RawImageOpen(fileName);
  246.   final = (TK_RGBImageRec *) malloc(sizeof(TK_RGBImageRec));
  247.   if (final == NULL) {
  248.     fprintf(stderr, "Out of memory!\n");
  249.     return NULL;
  250.   }
  251.   final->sizeX = raw->sizeX;
  252.   final->sizeY = raw->sizeY;
  253.   final->components = raw->sizeZ;
  254.   RawImageGetData(raw, final);
  255.   RawImageClose(raw);
  256.   return final;
  257. }
  258.  
  259. static void 
  260. FreeImage(TK_RGBImageRec * image)
  261. {
  262.   free(image->data);
  263.   free(image);
  264. }
  265.  
  266. /* 
  267.  * Load an SGI .rgb file and generate a set of 2-D mipmaps from it.
  268.  * Input:  imageFile - name of .rgb to read
  269.  *         intFormat - internal texture format to use, or number of components
  270.  * Return:  GL_TRUE if success, GL_FALSE if error.
  271.  */
  272. GLboolean 
  273. LoadRGBMipmaps(const char *imageFile, GLint intFormat)
  274. {
  275.   GLint error;
  276.   GLenum format;
  277.   TK_RGBImageRec *image;
  278.  
  279.   image = tkRGBImageLoad(imageFile);
  280.   if (!image) {
  281.     return GL_FALSE;
  282.   }
  283.   if (image->components == 3) {
  284.     format = GL_RGB;
  285.   } else if (image->components == 4) {
  286.     format = GL_RGBA;
  287.   } else if (image->components == 1) {
  288.     format = GL_LUMINANCE;
  289.     intFormat = 1;
  290.   } else {
  291.     /* not implemented */
  292.     fprintf(stderr,
  293.       "Error in LoadRGBMipmaps %d-component images not implemented\n",
  294.       image->components);
  295.     return GL_FALSE;
  296.   }
  297.  
  298.   error = gluBuild2DMipmaps(GL_TEXTURE_2D,
  299.     intFormat,
  300.     image->sizeX, image->sizeY,
  301.     format,
  302.     GL_UNSIGNED_BYTE,
  303.     image->data);
  304.  
  305.   FreeImage(image);
  306.   return error ? GL_FALSE : GL_TRUE;
  307. }
  308.